package cn.com.pc.content.controller;

import cn.com.pc.aaa.Constants;
import cn.com.pc.aaa.model.Identity;
import cn.com.pc.content.annotation.LogRequired;
import cn.com.pc.content.domain.audit.AuditStatus;
import cn.com.pc.content.domain.Biz;
import cn.com.pc.content.domain.content.ContentType;
import cn.com.pc.content.domain.Site;
import cn.com.pc.content.domain.video.Video;
import cn.com.pc.content.domain.video.VideoNotFoundException;
import cn.com.pc.content.dto.PageResult;
import cn.com.pc.content.dto.Sort;
import cn.com.pc.content.dto.VideoDTO;
import cn.com.pc.content.dto.VideoForm;
import cn.com.pc.content.service.ContentService;
import cn.com.pc.content.util.BeanUtils;
import cn.com.pc.content.util.IpUtils;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashSet;

/**
 * 视频 controller
 */
@RestController
@RequestMapping("/videos")
@Slf4j
public class VideoController {

    @Autowired
    private ContentService contentService;

    @Autowired
    private HttpServletRequest request;

    /**
     * 查询视频列表
     * @param site
     * @param biz
     * @param videoForm
     * @param sort
     * @return
     */
    @GetMapping
    public PageResult<?> listVideos(@RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, VideoForm videoForm, Sort sort) {
        videoForm.setSite(site);
        videoForm.setBiz(biz);
        return contentService.listContentByForm(videoForm, sort, ContentType.Video);
    }


    /**
     * 查询视频详情
     * @param site
     * @param biz
     * @param videoId
     * @return
     */
    @GetMapping("/{videoId:\\w+}")
    public VideoDTO getVideo(@RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, @PathVariable("videoId") String videoId) {
        VideoDTO video = (VideoDTO) contentService.getContent(videoId, site, biz, ContentType.Video);
        if (video == null) {
            throw new VideoNotFoundException();
        }
        return video;
    }


    /**
     * 新增视频
     * @param site
     * @param biz
     * @param videoDTO
     * @return
     * @throws IOException
     */
    @PostMapping
    @LogRequired(operation = "'新增视频' + #_return")
    public String createVideo(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute("biz") Biz biz, @Validated @RequestBody VideoDTO videoDTO) {
        // 查重
        Video video = (Video) contentService.getContentByReferId(videoDTO.getReferId(), site, biz, ContentType.Video);
        if (video != null) {
            videoDTO.setUpdatedBy(identity.getName());
            videoDTO.setUpdatedAt(LocalDateTime.now());
            videoDTO.setIp(IpUtils.getIp(request));
            video = (Video) contentService.updateContent(videoDTO, video, ContentType.Video);
            return video.getId();
        }

        videoDTO.setSite(site);
        videoDTO.setBiz(biz);
        videoDTO.setCreatedAt(LocalDateTime.now());
        videoDTO.setCreatedBy(identity.getName());
        videoDTO.setUpdatedAt(LocalDateTime.now());
        videoDTO.setUpdatedBy(identity.getName());
        videoDTO.setIp(IpUtils.getIp(request));

        video = new Video();
        video = (Video) contentService.createContent(videoDTO, video, ContentType.Video);
        return video.getId();
    }


    /**
     * 修改视频
     * @param site
     * @param biz
     * @param videoId
     * @param videoDTO
     * @return
     */
    @PutMapping("/{videoId:\\w+}")
    @LogRequired(operation = "'修改视频' + #videoId")
    public Video updateVideo(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, @PathVariable("videoId") String videoId, @Validated @RequestBody VideoDTO videoDTO) {
        Video video = (Video) contentService.getContentById(videoId, ContentType.Video);
        if (video == null || video.getSite() != site) {
            throw new VideoNotFoundException();
        }

        videoDTO.setUpdatedBy(identity.getName());
        videoDTO.setUpdatedAt(LocalDateTime.now());
        videoDTO.setIp(IpUtils.getIp(request));
        try {
            request.setAttribute("operation", "，修改属性" + BeanUtils.comparePropertyIgnore(video, videoDTO, "id", "ip", "auditStatus", "risk", "statData", "createdAt", "createdBy", "updatedAt", "updatedBy", "onShelve"));
        } catch (Exception e) {
            log.warn("视频{}生成修改日志有误", videoId);
            e.printStackTrace();
        }
        return (Video) contentService.updateContent(videoDTO, video, ContentType.Video);
    }


    /**
     * 部分修改视频
     * @param site
     * @param biz
     * @param videoDTO
     * @return
     */
    @PatchMapping
    @LogRequired(operation = "'部分修改视频' + #_return.getId()")
    public Video partialUpdateVideo(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, @RequestBody VideoDTO videoDTO) {
        // 判空
        String referId = videoDTO.getReferId();
        String id = videoDTO.getId();
        Video video = null;
        if (StringUtils.hasLength(referId) && biz != null) {
            video = (Video) contentService.getContentByReferId(referId, site, biz, ContentType.Video);
        } else if (StringUtils.hasLength(id)){
            video = (Video) contentService.getContentById(id, ContentType.Video);
        }

        if(video == null) {
            throw new VideoNotFoundException();
        }

        videoDTO.setUpdatedBy(identity.getName());
        videoDTO.setUpdatedAt(LocalDateTime.now());
        videoDTO.setIp(IpUtils.getIp(request));
        return (Video) contentService.partialUpdateContent(videoDTO, video, ContentType.Video);
    }


    /**
     * 上下架视频
     * @param site
     * @param biz
     * @param videoId
     * @return
     */
    @PatchMapping("/{videoId:\\w+}")
    @LogRequired(operation = "(#json.get('onShelve').asBoolean() == true ? '上架' : '下架') + '视频' + #videoId")
    public Video shelfVideo(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute(value = "biz",required = false) Biz biz, @PathVariable("videoId") String videoId, @RequestBody JsonNode json) {
        if (json.get("onShelve") == null) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "onShelve不能为空");
        }
        boolean onShelve = json.get("onShelve").asBoolean();

        Video video = (Video)contentService.getContentById(videoId, ContentType.Video);
        if(video == null || video.getSite() != site) {
            throw new VideoNotFoundException();
        }

        if (video.isOnShelve() == onShelve) {
            return video;
        }

        if (onShelve && video.getAuditStatus() != AuditStatus.Publish) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "视频未发布");
        }

        video.setUpdatedBy(identity.getName());
        video.setUpdatedAt(LocalDateTime.now());
        video.setOnShelve(onShelve);
        return (Video) contentService.shelveContent(video, ContentType.Video);
    }


    /**
     * 删除视频
     * @param site
     * @param biz
     * @param videoId
     */
    @DeleteMapping("/{videoId:\\w+}")
    @LogRequired(operation = "'删除视频' + #videoId")
    public void deleteVideo(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, @PathVariable("videoId") String videoId, HttpServletResponse response) {
        Video video = (Video) contentService.getContentById(videoId, ContentType.Video);
        if(video == null || video.getSite() != site) {
            throw new VideoNotFoundException();
        }

        video.setUpdatedBy(identity.getName());
        video.setUpdatedAt(LocalDateTime.now());
        contentService.deleteContent(video, ContentType.Video);
    }


    /**
     * 视频打标签
     * @param site
     * @param biz
     * @param videoId
     * @param videoDTO
     * @return
     */
    @PutMapping("/{videoId:\\w+}/tags")
    @LogRequired(operation = "'视频打标签' + #videoId")
    public Video updateVideoTag(@RequestAttribute(Constants.AAA_IDENTITY) Identity identity, @RequestAttribute("site") Site site, @RequestAttribute(value = "biz", required = false) Biz biz, @PathVariable("videoId") String videoId, @RequestBody VideoDTO videoDTO) {
        if (CollectionUtils.isEmpty(videoDTO.getTagIds())) {
            videoDTO.setTagIds(new HashSet<>() {});
        }
        // 判空
        Video video = (Video) contentService.getContentById(videoId, ContentType.Video);
        if(video == null || video.getSite() != site) {
            throw new VideoNotFoundException();
        }

        video.setUpdatedBy(identity.getName());
        video.setUpdatedAt(LocalDateTime.now());
        try {
            request.setAttribute("operation", "，修改属性" + BeanUtils.comparePropertyWith(video, videoDTO, "tagIds"));
        } catch (Exception e) {
            log.warn("视频{}生成修改日志有误", videoId);
            e.printStackTrace();
        }
        return (Video) contentService.updateContentTag(video, videoDTO, ContentType.Video);
    }
}
